#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <time.h>    
#define SERVER_PORT 502
const char *device = "DC400-0001";
const char *gongyi = "FCAW-S";
const char *hangong = "JSYJ-001";
const char *gongwei = "GDGW-T01-ZET02-JS01";

#define hton(a)  ((((uint16_t)a & 0xff00) >> 8) | (((uint16_t)a & 0x00ff) << 8))
typedef union FLOAT_CONV
{
    float f;
    char c[4];
}float_conv;


float BLEndianFloat(float value)
{
    float_conv d1,d2;
    d1.f = value;
    d2.c[0] = d1.c[1];
    d2.c[1] = d1.c[0];
    d2.c[2] = d1.c[3];
    d2.c[3] = d1.c[2];
    return d2.f;
}

#pragma pack(1)
typedef struct {
   uint16_t tid;
   uint16_t protocol;
   uint16_t len; //0x69
   uint8_t  slave;  //0x01
   uint8_t  function; //0x10
   uint16_t reg_addr;
   uint16_t reg_num;
   uint8_t  reg_len;
   char time[12];
   char device[10];
   char gongyi[10];
   char hangong[10];
   char gongwei[20];
   float current;
   float voltage;
   float sssd;
   float airflu;
   ////
   float speed;
   float hqbf;
   float hqbs;
   float hjcd;
   float hjjd;
}modbus_t;
#pragma pack()

void *modbus_alloc(uint8_t slave){
    modbus_t *ctx = (modbus_t *)malloc(sizeof(modbus_t));
    memset(ctx, 0, sizeof(modbus_t));
    ctx->tid = 0x0000;
    ctx->protocol = 0x00;
    ctx->len = hton(0x69);
    ctx->slave = slave;
    ctx->function = 0x10;
    ctx->reg_addr = hton(0x0000);
    ctx->reg_num = hton(0x31);
    ctx->reg_len = 0x62;
    return (void *)ctx;
}

int modbus_set_device(void *ctx, const char*device, const char *gongyi, const char*hangong, const char *gongwei){
    if (ctx == NULL) {
        return -1;
    }
    modbus_t * lctx = (modbus_t *)ctx;
    size_t l = strlen(device);
    int i = 0;
    for (; i < l; i+=2) {
        lctx->device[i] = device[i+1];
        lctx->device[i + 1] = device[i];
    }
    printf("%d, %s\n",(int)l, lctx->device);
    i = 0;
    l = strlen(gongyi);
    for (; i < l; i+=2) {
        lctx->gongyi[i] = gongyi[i+1];
        lctx->gongyi[i + 1] = gongyi[i];
    }
    printf("%d, %s\n",(int)l, lctx->gongyi);
    i = 0;
    l = strlen(hangong);
    for (; i < l; i+=2) {
        lctx->hangong[i] = hangong[i+1];
        lctx->hangong[i + 1] = hangong[i];
    }
    printf("%d, %s\n", (int)l, lctx->hangong);
    i = 0;
    l = strlen(gongwei);
    for (; i < l; i+=2) {
        lctx->gongwei[i] = gongwei[i+1];
        lctx->gongwei[i + 1] = gongwei[i];
    }
    printf("%d, %s\n", (int)l, lctx->gongwei);
    return 0;
}

int modbus_set_first(void *ctx, float current, float voltage, float sssd, float airflu)
{
    if (ctx == NULL) {
        return -1;
    }
    modbus_t * lctx = (modbus_t *)ctx;
    lctx->current = current;
    lctx->voltage = voltage;
    lctx->sssd = sssd;
    lctx->airflu = airflu;
    return 0;
}
int modbus_set_second(void *ctx, float hjsd, float hqbf, float hqbs, float hjcd, float hjjd)
{
    if (ctx == NULL) {
        return -1;
    }
    modbus_t * lctx = (modbus_t *)ctx;
    return 0;
}
static int __modbus_set_time(void *ctx){
    if (ctx == NULL) {
        return -1;
    }
    modbus_t * lctx = (modbus_t *)ctx;
    time_t   now;
    struct   tm *timenow;
    time(&now);
    timenow = localtime(&now);
    char buf[13];
    strftime(buf, sizeof(buf), "%y%m%d%H%M%S",  timenow);
    int i = 0;
    for (;i<12;i+=2) {
        lctx->time[i] = buf[i+1];
        lctx->time[i+1] = buf[i];
    }
    printf("%s\n", buf);
    return 0;
}

int modbus_modify(void *ctx){
    if (ctx == NULL) {
        return -1;
    }
    uint16_t temp;
    modbus_t * lctx = (modbus_t *)ctx;

    temp = hton(lctx->tid) + 1;
    lctx->tid = hton(temp);
    lctx->current = BLEndianFloat(lctx->current);
    lctx->voltage = BLEndianFloat(lctx->voltage);
    lctx->sssd = BLEndianFloat(lctx->sssd);
    lctx->airflu = BLEndianFloat(lctx->airflu);
    __modbus_set_time(ctx);
}

int main()
{
    void *p = modbus_alloc(1);
    modbus_set_device(p, device, gongyi, hangong, gongwei);

    #if 1
    int skt;
    struct sockaddr_in serverAddr;

    if((skt = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        perror("socket");
	return 1;
    }
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(SERVER_PORT);
    serverAddr.sin_addr.s_addr = inet_addr("101.201.239.239");
    if(connect(skt, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0)
    {
        perror("connect");
        return 1;
    }
    printf("连接到主机...\n");
    int i;
    int j = 0;
    while (1)
    {
        modbus_set_first(p, 220, j++, 1, 1);
        modbus_modify(p);
        sleep(1);
        i = send(skt, p, sizeof(modbus_t), 0);
        printf("%d\n",i);
    }
    perror("");
    close(skt);
    #endif
    return 0;
}
